from pathlib import Path
import json
import base64
p0 = Path.cwd().parent / 'log'
p = p0.glob('*.json')

o = json.loads(next(p).read_text(encoding='utf-8'))
o

# 1. see some fields
s = o['Topo_map_result']
s = s.removeprefix("_HTML:b'")
s = s.removesuffix("'")
s
# 1.1 decode base64 text
# s = base64.b64decode(s.encode('utf-8')).decode('utf-8')
s = base64.b64decode(s).decode('utf-8')  # ok
# s = base64.b64decode(s)  # character missing...
print(s)

# --------------------------------------------------
# 2. wrap a function
def d(s: str, prefix='HTML') -> str:           # base64 decode a string
    s = s.removeprefix(f"_{prefix}:b'").removesuffix("'")
    return base64.b64decode(s).decode('utf-8')

l = o['TestClass']['steps']['stepLists']
d(l[0]['Title'][1])
#   ^ the Action id
d(l[0]['CheckCommand']['Title'][1])  # the command

# 🦜 : inside this CheckCommand obj, there's a send_XXX and CheckCommand_XXX object
c = l[0]['CheckCommand']
a = [(k,c[k]) for k in c if k.startswith('send_')][0]
b = [(k,c[k]) for k in c if k.startswith('CheckCommand_')][0]
a
b
# a['Result'] == 'PASS'
print(d(a[1]['all_cmds_response'], 'CMD'))
# print(d(a[1]['last_cmd_response'], 'CMD')) # 🦜 : subset of previous one
# a['Result'] == 'PASS'

print(d(b[1]['all_cmds_response']))

# --------------------------------------------------
# 3. try parse to log.yml
l0 = []
for x in l:
    c = x['CheckCommand']
    if c['Result'] == 'PASS':
        l0.append('ok')
        continue
    # 3.1 get the 'whole-output' and the warning
    a = [(k,c[k]) for k in c if k.startswith('send_')][0]
    b = [(k,c[k]) for k in c if k.startswith('CheckCommand_')][0]

# --------------------------------------------------
# 4. decode base64-encoded strings in a JSON object

import json
import base64

def decode_base64_strings(obj):
    """
    Recursively traverse a JSON object and decode base64-encoded strings
    that have the format "_HTML:b'<base64>'" or "_CMD:b'<base64>'"
    """
    if isinstance(obj, dict):
        # Recursively process dictionary values
        return {key: decode_base64_strings(value) for key, value in obj.items()}
    
    elif isinstance(obj, list):
        # Recursively process list items
        return [decode_base64_strings(item) for item in obj]
    
    elif isinstance(obj, str):
        # Check if string matches the encoded format
        if obj.startswith('_HTML:b\'') and obj.endswith('\''):
            try:
                return d(obj, 'HTML')
            except Exception:
                # If decoding fails, return original string
                return obj
        elif obj.startswith('_CMD:b\'') and obj.endswith('\''):
            try:
                return d(obj, 'CMD')
            except Exception:
                # If decoding fails, return original string
                return obj
        else:
            # Return string as-is if it doesn't match the pattern
            return obj
    
    else:
        # Return primitive types (int, float, bool, None) as-is
        return obj

def d(s: str, prefix='HTML') -> str:
    """Base64 decode a string with the given prefix"""
    s = s.removeprefix(f"_{prefix}:b'").removesuffix("'")
    return base64.b64decode(s).decode('utf-8')

# Usage example:
# o = json.loads(...)
# o = decode_base64_strings(o)
p0 = Path.cwd().parent / 'log'
p = next(p0.glob('*.json'))
o = json.loads(p.read_text(encoding='utf-8'))
o_decoded = decode_base64_strings(o)
p1 = p.with_suffix('.decoded.json')
p1.write_text(json.dumps(o_decoded, indent=2, ensure_ascii=False), encoding='utf-8')
